package dao

import (
	"errors"
	"user_srv/basic/config"
	"user_srv/handler/models"
	"user_srv/untils"
)

// GetSwipeCandidates 获取用户的滑动候选用户列表
// 参数：userId - 用户ID, limit - 获取数量限制
// 返回：候选用户列表和错误信息
func GetSwipeCandidates(userId uint64, limit int) ([]models.SwipeCandidate, error) {
	var candidates []models.SwipeCandidate

	// 如果limit为0或负数，设置默认值
	if limit <= 0 {
		limit = 10
	}

	// 查询候选用户，按匹配分数降序排列
	err := config.DB.Where("user_id = ? AND status = 1", userId).
		Order("match_score DESC").
		Limit(limit).
		Find(&candidates).Error

	if err != nil {
		return nil, errors.New("获取候选用户失败：" + err.Error())
	}

	return candidates, nil
}

// CreateSwipeRecord 创建滑动记录
// 参数：userId - 滑动用户ID, targetId - 被滑动用户ID, action - 滑动动作, matchScore - 匹配分数
// 返回：错误信息
func CreateSwipeRecord(userId, targetId uint64, action int8, matchScore float64) error {
	swipeRecord := models.SwipeRecord{
		UserId:     userId,
		TargetId:   targetId,
		Action:     action,
		MatchScore: matchScore,
	}

	err := swipeRecord.Create()
	if err != nil {
		return errors.New("创建滑动记录失败：" + err.Error())
	}

	return nil
}

// CheckSwipeRecord 检查是否已经滑动过某个用户
// 参数：userId - 用户ID, targetId - 目标用户ID
// 返回：是否已滑动和错误信息
func CheckSwipeRecord(userId, targetId uint64) (bool, error) {
	var swipeRecord models.SwipeRecord
	swipeRecord.UserId = userId
	swipeRecord.TargetId = targetId

	err := swipeRecord.GetByUserAndTarget()
	if err != nil {
		// 如果没有找到记录，说明没有滑动过
		if err.Error() == "record not found" {
			return false, nil
		}
		return false, errors.New("检查滑动记录失败：" + err.Error())
	}

	return true, nil
}

// CreateMatchRecord 创建匹配记录
// 参数：user1Id, user2Id - 两个用户ID, matchScore - 匹配分数
// 返回：匹配记录ID和错误信息
func CreateMatchRecord(user1Id, user2Id uint64, matchScore float64) (uint64, error) {
	matchRecord := models.MatchRecord{
		User1Id:    user1Id,
		User2Id:    user2Id,
		MatchScore: matchScore,
		Status:     1, // 正常状态
	}

	err := matchRecord.Create()
	if err != nil {
		return 0, errors.New("创建匹配记录失败：" + err.Error())
	}

	return matchRecord.Id, nil
}

// CheckMatchRecord 检查两个用户是否已经匹配
// 参数：user1Id, user2Id - 两个用户ID
// 返回：是否已匹配和错误信息
func CheckMatchRecord(user1Id, user2Id uint64) (bool, error) {
	var matchRecord models.MatchRecord
	matchRecord.User1Id = user1Id
	matchRecord.User2Id = user2Id

	err := matchRecord.GetByUsers()
	if err != nil {
		// 如果没有找到记录，说明没有匹配
		if err.Error() == "record not found" {
			return false, nil
		}
		return false, errors.New("检查匹配记录失败：" + err.Error())
	}

	return true, nil
}

// GetMatchList 获取用户的匹配列表
// 参数：userId - 用户ID, page - 页码, pageSize - 每页数量
// 返回：匹配列表和总数量
func GetMatchList(userId uint64, page, pageSize int) ([]models.MatchRecord, int64, error) {
	var matches []models.MatchRecord
	var total int64

	// 如果pageSize为0或负数，设置默认值
	if pageSize <= 0 {
		pageSize = 20
	}

	// 如果page为0或负数，设置默认值
	if page <= 0 {
		page = 1
	}

	// 计算偏移量
	offset := (page - 1) * pageSize

	// 查询匹配记录总数
	err := config.DB.Model(&models.MatchRecord{}).
		Where("(user1_id = ? OR user2_id = ?) AND status = 1", userId, userId).
		Count(&total).Error
	if err != nil {
		return nil, 0, errors.New("获取匹配总数失败：" + err.Error())
	}

	// 查询匹配记录列表
	err = config.DB.Where("(user1_id = ? OR user2_id = ?) AND status = 1", userId, userId).
		Order("created_at DESC").
		Offset(offset).
		Limit(pageSize).
		Find(&matches).Error
	if err != nil {
		return nil, 0, errors.New("获取匹配列表失败：" + err.Error())
	}

	return matches, total, nil
}

// UnmatchUser 解除匹配
// 参数：userId - 用户ID, matchId - 匹配记录ID
// 返回：错误信息
func UnmatchUser(userId, matchId uint64) error {
	var matchRecord models.MatchRecord
	matchRecord.Id = matchId

	// 先查询匹配记录是否存在且属于该用户
	err := config.DB.Where("id = ? AND (user1_id = ? OR user2_id = ?) AND status = 1",
		matchId, userId, userId).First(&matchRecord).Error
	if err != nil {
		return errors.New("匹配记录不存在或无权限操作")
	}

	// 更新状态为解除匹配
	matchRecord.Status = 2
		err = matchRecord.Update()
	if err != nil {
		return errors.New("解除匹配失败：" + err.Error())
	}

	return nil
}

// GenerateSwipeCandidates 为用户生成候选用户（智能补充 + 自动扩大范围）
// 参数：userId - 用户ID, count - 生成数量
// 返回：错误信息
func GenerateSwipeCandidates(userId uint64, count int) error {
	// 如果count为0或负数，设置默认值
	if count <= 0 {
		count = 20
	}

	// 获取用户信息
	var user models.User
	user.Id = userId
	err := user.GetById()
	if err != nil {
		return errors.New("获取用户信息失败：" + err.Error())
	}

	// 获取用户的兴趣标签
	userInterests, err := GetUserInterests(userId)
	if err != nil {
		return errors.New("获取用户兴趣失败：" + err.Error())
	}

	// 构建兴趣ID列表
	var interestIds []uint64
	for _, interest := range userInterests {
		interestIds = append(interestIds, interest.Id)
	}

	// 分级查询策略（自动扩大搜索范围）
	var candidates []models.User

	// 优先级1：10km + 兴趣匹配
	if user.Latitude != nil && user.Longitude != nil && len(interestIds) > 0 {
		candidates = queryCandidatesByDistance(userId, user, interestIds, 10, count*2)
	}

	// 优先级2：如果不足，扩大到20km
	if len(candidates) < count && user.Latitude != nil && user.Longitude != nil {
		additional := queryCandidatesByDistance(userId, user, interestIds, 20, count*2)
		candidates = mergeCandidates(candidates, additional, count*2)
	}

	// 优先级3：如果还不足，扩大到50km
	if len(candidates) < count && user.Latitude != nil && user.Longitude != nil {
		additional := queryCandidatesByDistance(userId, user, interestIds, 50, count*2)
		candidates = mergeCandidates(candidates, additional, count*2)
	}

	// 优先级4：如果还不足，忽略兴趣限制，全国范围查询活跃用户
	if len(candidates) < count {
		additional := queryActiveUsersNationwide(userId, user, count*2)
		candidates = mergeCandidates(candidates, additional, count*2)
	}

	// 优先级5：如果还不足，查询30天前左滑过的用户（过期重刷）
	if len(candidates) < count {
		additional := queryExpiredSwipedUsers(userId, user, 30, count)
		candidates = mergeCandidates(candidates, additional, count*2)
	}

	// 为每个候选用户计算分数并创建记录
	type CandidateWithScore struct {
		User  models.User
		Score float64
	}

	var candidatesWithScore []CandidateWithScore
	for _, candidate := range candidates {
		// 计算匹配分数
		matchScore := calculateMatchScore(user, candidate, userInterests)
		candidatesWithScore = append(candidatesWithScore, CandidateWithScore{
			User:  candidate,
			Score: matchScore,
		})
	}

	// 按分数降序排序
	for i := 0; i < len(candidatesWithScore)-1; i++ {
		for j := i + 1; j < len(candidatesWithScore); j++ {
			if candidatesWithScore[i].Score < candidatesWithScore[j].Score {
				candidatesWithScore[i], candidatesWithScore[j] = candidatesWithScore[j], candidatesWithScore[i]
			}
		}
	}

	// 取前count个
	if len(candidatesWithScore) > count {
		candidatesWithScore = candidatesWithScore[:count]
	}

	// 创建候选用户记录
	for _, cws := range candidatesWithScore {
		candidateRecord := models.SwipeCandidate{
			UserId:      userId,
			CandidateId: cws.User.Id,
			MatchScore:  cws.Score,
			Reason:      generateMatchReason(user, cws.User, userInterests),
			Status:      1, // 待滑动状态
		}

		err = candidateRecord.Create()
		if err != nil {
			// 如果创建失败，继续处理下一个
			continue
		}
	}

	return nil
}

// GenerateNearbyCandidates 专门生成附近的候选用户（基于LBS）
// 参数：userId - 用户ID, radiusKm - 搜索半径（千米）, count - 生成数量
// 返回：错误信息
func GenerateNearbyCandidates(userId uint64, radiusKm float64, count int) error {
	// 获取用户信息
	var user models.User
	user.Id = userId
	err := user.GetById()
	if err != nil {
		return errors.New("获取用户信息失败：" + err.Error())
	}

	// 检查是否有位置信息
	if user.Latitude == nil || user.Longitude == nil {
		return errors.New("请先更新您的位置信息")
	}

	// 获取附近的用户
	nearbyUsers, err := GetNearbyUsers(userId, radiusKm, count)
	if err != nil {
		return err
	}

	// 获取用户兴趣
	userInterests, _ := GetUserInterests(userId)

	// 为附近用户创建候选记录
	for _, nearbyUser := range nearbyUsers {
		// 计算匹配分数
		matchScore := calculateMatchScore(user, nearbyUser, userInterests)

		// 创建候选用户记录
		candidateRecord := models.SwipeCandidate{
			UserId:      userId,
			CandidateId: nearbyUser.Id,
			MatchScore:  matchScore,
			Reason:      generateMatchReason(user, nearbyUser, userInterests),
			Status:      1,
		}

		err = candidateRecord.Create()
		if err != nil {
			return err
		}
	}

	return nil
}

// calculateMatchScore 计算匹配分数
// 参数：user - 用户信息, candidate - 候选用户信息, userInterests - 用户兴趣列表
// 返回：匹配分数
func calculateMatchScore(user, candidate models.User, userInterests []models.Interest) float64 {
	score := 0.0

	// 基础分数 20%
	score += 0.2

	// 兴趣匹配 40%
	if len(userInterests) > 0 {
		candidateInterests, err := GetUserInterests(candidate.Id)
		if err == nil {
			// 计算兴趣重叠度
			commonInterests := 0
			for _, userInterest := range userInterests {
				for _, candidateInterest := range candidateInterests {
					if userInterest.Id == candidateInterest.Id {
						commonInterests++
						break
					}
				}
			}
			// 兴趣匹配分数
			score += float64(commonInterests) / float64(len(userInterests)) * 0.4
		}
	}

	// 距离匹配 20%（如果有位置信息）
	if user.Latitude != nil && user.Longitude != nil &&
		candidate.Latitude != nil && candidate.Longitude != nil {
		distance := untils.CalculateDistance(
			*user.Latitude, *user.Longitude,
			*candidate.Latitude, *candidate.Longitude,
		)

		// 距离评分：距离越近分数越高
		// 1km内: +0.20
		// 5km内: +0.15
		// 10km内: +0.10
		// 20km内: +0.05
		// 20km外: +0.02
		if distance < 1 {
			score += 0.20
		} else if distance < 5 {
			score += 0.15
		} else if distance < 10 {
			score += 0.10
		} else if distance < 20 {
			score += 0.05
		} else {
			score += 0.02
		}
	}

	// 在线状态奖励 10%
	if candidate.Status == 1 {
		score += 0.1
	}

	// 实名认证奖励 10%
	if candidate.IdCardVerificationStatus == 2 {
		score += 0.1
	}

	// 确保分数在0-1之间
	if score > 1.0 {
		score = 1.0
	}

	return score
}

// generateMatchReason 生成匹配理由
// 参数：user - 用户信息, candidate - 候选用户信息, userInterests - 用户兴趣列表
// 返回：匹配理由
func generateMatchReason(user, candidate models.User, userInterests []models.Interest) string {
	reasons := []string{}

	// 距离理由（优先显示）
	if user.Latitude != nil && user.Longitude != nil &&
		candidate.Latitude != nil && candidate.Longitude != nil {
		distance := untils.CalculateDistance(
			*user.Latitude, *user.Longitude,
			*candidate.Latitude, *candidate.Longitude,
		)

		distanceStr := untils.FormatDistance(distance)
		if distance < 1 {
			reasons = append(reasons, "距离"+distanceStr+"·超近")
		} else if distance < 5 {
			reasons = append(reasons, "距离"+distanceStr+"·很近")
		} else if distance < 20 {
			reasons = append(reasons, "距离"+distanceStr)
		}
	}

	// 兴趣匹配理由
	if len(userInterests) > 0 {
		candidateInterests, err := GetUserInterests(candidate.Id)
		if err == nil {
			count := 0
			for _, userInterest := range userInterests {
				for _, candidateInterest := range candidateInterests {
					if userInterest.Id == candidateInterest.Id {
						if count < 2 { // 最多显示2个共同兴趣
							reasons = append(reasons, "共同喜欢"+userInterest.Name)
						}
						count++
						break
					}
				}
			}
		}
	}

	// 在线状态理由
	if candidate.Status == 1 {
		reasons = append(reasons, "当前在线")
	}

	// 实名认证理由
	if candidate.IdCardVerificationStatus == 2 {
		reasons = append(reasons, "已实名认证")
	}

	// 如果没有特殊理由，使用默认理由
	if len(reasons) == 0 {
		return "系统推荐"
	}

	// 返回前3个理由
	if len(reasons) > 3 {
		reasons = reasons[:3]
	}

	result := ""
	for i, reason := range reasons {
		if i > 0 {
			result += "、"
		}
		result += reason
	}

	return result
}

// queryCandidatesByDistance 按距离查询候选用户
func queryCandidatesByDistance(userId uint64, user models.User, interestIds []uint64, radiusKm float64, limit int) []models.User {
	var candidates []models.User

	if user.Latitude == nil || user.Longitude == nil {
		return candidates
	}

	// 计算大致范围
	latRange := radiusKm / 111.0
	lonRange := radiusKm / 111.0

	query := config.DB.Where("id != ? AND sex != ? AND status = 1", userId, user.Sex).
		Where("id NOT IN (SELECT target_id FROM swipe_record WHERE user_id = ?)", userId).
		Where("latitude IS NOT NULL AND longitude IS NOT NULL").
		Where("latitude BETWEEN ? AND ?", *user.Latitude-latRange, *user.Latitude+latRange).
		Where("longitude BETWEEN ? AND ?", *user.Longitude-lonRange, *user.Longitude+lonRange)

	// 如果有兴趣限制
	if len(interestIds) > 0 {
		query = query.Where("id IN (SELECT user_id FROM user_interest WHERE interest_id IN (?))", interestIds)
	}

	query.Limit(limit).Find(&candidates)

	return candidates
}

// queryActiveUsersNationwide 查询全国活跃用户（无距离限制）
func queryActiveUsersNationwide(userId uint64, user models.User, limit int) []models.User {
	var candidates []models.User

	// 查询最近7天活跃的用户
	query := config.DB.Where("id != ? AND sex != ? AND status = 1", userId, user.Sex).
		Where("id NOT IN (SELECT target_id FROM swipe_record WHERE user_id = ?)", userId).
		Where("updated_at > DATE_SUB(NOW(), INTERVAL 7 DAY)"). // 7天内活跃
		Order("updated_at DESC")                               // 按活跃度排序

	query.Limit(limit).Find(&candidates)

	return candidates
}

// queryExpiredSwipedUsers 查询过期的已滑动用户（可以重新出现）
func queryExpiredSwipedUsers(userId uint64, user models.User, expiredDays int, limit int) []models.User {
	var candidates []models.User

	// 查询N天前左滑的用户
	query := config.DB.Where("id != ? AND sex != ? AND status = 1", userId, user.Sex).
		Where("id IN (SELECT target_id FROM swipe_record WHERE user_id = ? AND action = 1 AND created_at < DATE_SUB(NOW(), INTERVAL ? DAY))",
			userId, expiredDays)

	query.Limit(limit).Find(&candidates)

	return candidates
}

// mergeCandidates 合并候选用户列表（去重）
func mergeCandidates(existing, additional []models.User, maxLimit int) []models.User {
	// 使用map去重
	idMap := make(map[uint64]bool)
	result := make([]models.User, 0)

	// 先添加已有的
	for _, user := range existing {
		if !idMap[user.Id] {
			idMap[user.Id] = true
			result = append(result, user)
		}
	}

	// 再添加新的（去重）
	for _, user := range additional {
		if !idMap[user.Id] {
			idMap[user.Id] = true
			result = append(result, user)

			// 达到上限就停止
			if len(result) >= maxLimit {
				break
			}
		}
	}

	return result
}

// GetAvailableCandidatesCount 获取可用候选数量
func GetAvailableCandidatesCount(userId uint64) (int, error) {
	var count int64
	err := config.DB.Model(&models.SwipeCandidate{}).
		Where("user_id = ? AND status = 1", userId).
		Count(&count).Error

	if err != nil {
		return 0, err
	}

	return int(count), nil
}

// SmartRefillCandidates 智能补充候选池
// 当候选数量<10时自动补充到50个
func SmartRefillCandidates(userId uint64) error {
	// 检查当前候选数量
	count, err := GetAvailableCandidatesCount(userId)
	if err != nil {
		return err
	}

	// 如果候选数量充足，不需要补充
	if count >= 10 {
		return nil
	}

	// 自动补充到50个
	return GenerateSwipeCandidates(userId, 50)
}
